#ifndef COMMON_ETCD_H
#define COMMON_ETCD_H

#include <etcd/Client.hpp>
#include <etcd/KeepAlive.hpp>
#include <etcd/Response.hpp>
#include <etcd/Value.hpp>
#include <etcd/Watcher.hpp>
#include <functional>
#include <memory>

namespace chat {
class Registry {
   public:
    Registry(const std::string& host);

    /**
     * @brief 服务注册, etcd存储键值对信息 (key服务可以由val提供)
     * @param key[in]: key值
     * @param val[in]: val值
     */
    bool registry(const std::string& key, const std::string& val);

   private:
    std::shared_ptr<etcd::Client> client_ = nullptr;         // etcd客户端句柄
    std::shared_ptr<etcd::KeepAlive> keep_alive_ = nullptr;  // 保活对象
    int64_t lease_id_;                                       // 租约id
};

using RegistryPtr = std::shared_ptr<Registry>;

class Discovery {
   public:
    using callback_t = std::function<void(std::string, std::string)>;

    /**
     * @param host[in]: 主机地址
     * @param base_dir[in]: 服务发现时的根目录
     */
    Discovery(const std::string& host, const std::string& base_dir,
              callback_t put_cb, callback_t del_cb);

   private:
    void discovery(const std::string& base_dir);
    void callback(const etcd::Response& resp);

   private:
    std::shared_ptr<etcd::Client> client_ = nullptr;  // etcd客户端句柄

    // 监视对象，用于服务变化的通知
    std::shared_ptr<etcd::Watcher> watcher_ = nullptr;       
      
    callback_t put_cb_;  // 当有新的主机能提供服务，使用该回调
    callback_t del_cb_;  // 当监视服务的某个主机下线，使用该回调
};

using DiscoveryPtr = std::shared_ptr<Discovery>;
}  // namespace chat

#endif  // COMMON_ETCD_H
